﻿using SharpSoft.WPF.Adorners;
using SharpSoft.WPF.Masks;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Documents;
using System.Windows.Input;

namespace SharpSoft.WPF.Masks
{
    /// <summary>
    /// 用于创建遮罩层
    /// </summary>
    public class Mask
    {
        public Mask(VisualAdorner adorner, AdornerLayer adornerLayer, TimeSpan? timeout = null)
        {
            this.Adorner = adorner;
            this.AdornerLayer = adornerLayer;
            this.Model = new MaskViewModel(this);
            this.Timeout = timeout;

            var model = this.Model;
            if (this.Adorner != null)
            {
                if (this.Adorner.ContentVisual is System.Windows.FrameworkElement fe)
                {
                    fe.CommandBindings.Add(new CommandBinding(model.CloseCommand, new ExecutedRoutedEventHandler((s, e) =>
                    {
                        if (e.Parameter == null)
                        {
                            model.Result = null;
                        }
                        else if (e.Parameter is bool b)
                        {
                            model.Result = b;
                        }
                        else
                        {
                            model.Result = true;
                        }
                        this.Close();
                    }), null));
                    this.Model.CanWait = true;//未通过此函数设置信号灯释放时机的Mask不允许等待 
                    fe.DataContext = model;
                }
            }
            else
            {
                throw new Exception("装饰器对象未指定,无法创建遮罩层。");
            }


        }
        /// <summary>
        /// 倒计时
        /// </summary>
        private async void CountDown()
        {
            if (this.Timeout != null)
            {
                var t = this.Timeout.Value;
                while (t.TotalSeconds > 0)
                {
                    this.Model.CountDown = (int)Math.Round(t.TotalSeconds);
                    await Task.Delay(1000);
                    t = t - TimeSpan.FromSeconds(1);
                }
                this.Close();//倒计时结束关闭遮罩层
            }
        }

        /// <summary>
        /// 视图模型
        /// </summary>
        public MaskViewModel Model { get; private set; }
        /// <summary>
        /// 对话框超时时间
        /// </summary>
        public TimeSpan? Timeout { get; set; }
        /// <summary>
        /// 装饰器对象
        /// </summary>
        public VisualAdorner Adorner { get; internal set; }

        /// <summary>
        /// 所属装饰器层 
        /// </summary>
        public AdornerLayer AdornerLayer { get; internal set; }

        /// <summary>
        /// 关闭遮罩层
        /// </summary>
        public void Close()
        {
            if (this.Adorner != null && this.AdornerLayer != null)
            {
                this.AdornerLayer.Remove(this.Adorner);
            }
            this.Model.AutoResetEvent.Set();
        }
        /// <summary>
        /// 打开遮罩层
        /// </summary>
        public Mask Open()
        {

            if (this.Adorner != null && this.AdornerLayer != null)
            {
                this.AdornerLayer.Add(this.Adorner);
            }
            if (Timeout.HasValue)
            {//倒计时
                CountDown();
            }
            return this;
        }
        /// <summary>
        /// 设置遮罩层内容控件的视图模型
        /// </summary>
        /// <typeparam name="TModel"></typeparam>
        /// <returns></returns>
        public Mask ViewModel(Action<MaskViewModel> modelConfig)
        {
            MaskViewModel model = this.Model;
            modelConfig?.Invoke(model);

            return this;
        }
        /// <summary>
        /// 等待对话框结果
        /// </summary>
        /// <returns></returns>
        public async Task<MaskViewModel> WaitResultAsync()
        {
            if (!this.Model.CanWait)
            {
                throw new Exception("此Mask不允许等待，请先通过ViewModel函数设置Mask的视图模型。");
            }
            await Task.Run(this.Model.AutoResetEvent.WaitOne);
            return this.Model;
        }
    }

    /// <summary>
    /// 用于遮罩层交互数据的视图模型
    /// </summary>
    public class MaskViewModel : System.Windows.DependencyObject
    {
        protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
        {
            base.OnPropertyChanged(e);
        }

        public MaskViewModel(Mask mask)
        {
            Mask = mask;
            CloseCommand = new RoutedCommand("Close", typeof(MaskViewModel));
            this.AutoResetEvent = new System.Threading.AutoResetEvent(false);

        }

        public Mask Mask { get; private set; }

        /// <summary>
        /// 标题
        /// </summary>
        public object Title
        {
            get { return (object)GetValue(TitleProperty); }
            set { SetValue(TitleProperty, value); }
        }

        public static readonly DependencyProperty TitleProperty =
            DependencyProperty.Register("Title", typeof(object), typeof(MaskViewModel), new PropertyMetadata(null));


        /// <summary>
        /// 内容
        /// </summary>
        public object Content
        {
            get { return (object)GetValue(ContentProperty); }
            set { SetValue(ContentProperty, value); }
        }

        public static readonly DependencyProperty ContentProperty =
            DependencyProperty.Register("Content", typeof(object), typeof(MaskViewModel), new PropertyMetadata(0));



        /// <summary>
        /// 数据
        /// </summary>
        public object Data
        {
            get { return (object)GetValue(DataProperty); }
            set { SetValue(DataProperty, value); }
        }

        public static readonly DependencyProperty DataProperty =
            DependencyProperty.Register("Data", typeof(object), typeof(MaskViewModel), new PropertyMetadata(null));



        /// <summary>
        /// 倒计时
        /// </summary>
        public int? CountDown
        {
            get { return (int?)GetValue(CountDownProperty); }
            set { SetValue(CountDownProperty, value); }
        }

        public static readonly DependencyProperty CountDownProperty =
            DependencyProperty.Register("CountDown", typeof(int?), typeof(MaskViewModel), new PropertyMetadata(null));



        /// <summary>
        /// Mask关闭结果
        /// </summary>
        public bool? Result
        {
            get { return (bool?)GetValue(ResultProperty); }
            internal set { SetValue(ResultPropertyKey, value); }
        }
        private static DependencyPropertyKey ResultPropertyKey = DependencyProperty.RegisterReadOnly("Result", typeof(bool?), typeof(MaskViewModel), new PropertyMetadata(default(bool?)));
        public static DependencyProperty ResultProperty = ResultPropertyKey.DependencyProperty;



        public RoutedCommand CloseCommand { get; private set; }
        /// <summary>
        /// 信号灯
        /// </summary>
        public System.Threading.AutoResetEvent AutoResetEvent { get; private set; }
        /// <summary>
        /// 是否可以等待结果
        /// </summary>
        public bool CanWait { get; internal set; } = false;
    }

    /// <summary>
    /// 不能创建装饰器的异常
    /// </summary>

    [Serializable]
    public class CanNotCreateAdornerException : Exception
    {
        public CanNotCreateAdornerException() { }
        public CanNotCreateAdornerException(string message) : base(message) { }
        public CanNotCreateAdornerException(string message, Exception inner) : base(message, inner) { }
        protected CanNotCreateAdornerException(
          System.Runtime.Serialization.SerializationInfo info,
          System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
    }
}
